package postgres

import (
	"context"
	"fmt"
	"quipus/internal/database/model"

	apb "quipus/proto/gen/assist"

	_ "github.com/jackc/pgx/v5/stdlib"
	_ "github.com/joho/godotenv/autoload"
	"google.golang.org/protobuf/encoding/protojson"
)

func (p *PGDB) CreateResource(ctx context.Context, create *model.Resource) error {
	p.query()
	qdo := q.WithContext(ctx)
	err := qdo.Resource.Create(create)
	if err != nil {
		return err
	}

	return nil
}

func (p *PGDB) ListResources(ctx context.Context, find *apb.FindResource) ([]*model.Resource, int64, error) {
	p.query()
	qdo := q.WithContext(ctx)
	resouce := qdo.Resource
	if find.Id > 0 {
		resouce = resouce.Where(q.Resource.ID.Eq(find.Id))
	}

	if len(find.Uid) > 0 {
		resouce = resouce.Where(q.Resource.UID.Eq(find.Uid))
	}

	if find.CreatorId > 0 {
		resouce = resouce.Where(q.Resource.CreatorID.Eq(find.CreatorId))
	}

	if len(find.Filename) > 0 {
		resouce = resouce.Where(q.Resource.Filename.Eq(find.Filename))
	}

	if len(find.FilenameSearch) > 0 {
		resouce = resouce.Where(q.Resource.Filename.Like(fmt.Sprintf("%%%s%%", find.FilenameSearch)))
	}

	if find.KnotId > 0 {
		resouce = resouce.Where(q.Resource.KnotID.Eq(find.KnotId))
	}

	if find.HasRelatedKnot {
		resouce = resouce.Where(q.Resource.KnotID.IsNotNull())
	}

	if find.StorageType != "" {
		resouce = resouce.Where(q.Resource.StorageType.Eq(find.StorageType))
	}

	resouce.Order(q.Resource.UpdatedTs.Desc())
	limit := find.Limit
	if limit == 0 {
		limit = 10
	}

	return resouce.FindByPage(int(find.Offset), int(limit))
}

func (p *PGDB) UpdateResource(ctx context.Context, update *apb.UpdateResource) error {
	p.query()
	qdo := q.WithContext(ctx)
	resouce := qdo.Resource
	resouce = resouce.Where(q.Resource.ID.Eq(update.Id))

	updateValue := model.Resource{}
	if update.Uid != "" {
		updateValue.UID = update.Uid
	}

	if update.UpdatedTs != nil {
		updateValue.UpdatedTs = update.UpdatedTs.GetSeconds()
	}

	if update.Filename != "" {
		updateValue.Filename = update.Filename
	}

	if update.KnotId > 0 {
		updateValue.KnotID = update.KnotId
	}

	if update.Reference != "" {
		updateValue.Reference = update.Reference
	}

	if update.Payload != nil {
		p, err := protojson.Marshal(update.Payload)
		if err != nil {
			return err
		}
		updateValue.Payload = string(p)
	}

	_, e := resouce.Updates(updateValue)

	return e
}

func (p *PGDB) DeleteResource(ctx context.Context, delete *apb.DeleteResource) error {
	p.query()
	resouce := q.WithContext(ctx).Resource
	_, err := resouce.Where(q.Resource.ID.Eq(delete.Id)).Delete()
	return err
}

func (p *PGDB) GetResource(ctx context.Context, find *apb.FindResource) (*model.Resource, error) {
	p.query()
	resouce := q.WithContext(ctx).Resource
	resouce = resouce.Where(q.Resource.ID.Eq(find.Id))
	return resouce.First()
}
